﻿var played={}, mysql=require('mysql'),
http=require('http'),
url=require('url'),
crypto=require('crypto'),
querystring=require('querystring'),
config=require('./config.js'),
calc=require('./kj-data/kj-calc-time.js'),  //开奖时间模计算
exec=require('child_process').exec,
execPath=process.argv.join(" "),   //执行路径
//onparse=require('./kj-data/parse-string.js'),
parse=require('./kj-data/parse-calc-count.js');
require('./String-ext.js');

var fs = require('fs');

/**
 * 日志跟踪 
 */
var logger = require('tracer').console({
	transport : function(data) {
		
		fs.open('./log/file.log', 'a', 0666, function(e, id) {
			fs.write(id, data.output+"\n", null, 'utf8', function() {
				fs.close(id, function() {
				});
			});
		});
	},
	format : [
	          "{{timestamp}} (in {{file}}:{{line}}) {{message}}",     //default format
	          {
	        	  error : "{{timestamp}} <{{title}}> {{message}} (in {{file}}:{{line}})\nCall Stack:\n{{stack}}" // error format
	          }	
	],
	dateformat : "yyyy-mm-dd HH:MM:ss",
});

var express = require('express');
var app = express();

// 抛出未知出错时处理
process.on('uncaughtException', function(e){
//	console.log(e.stack);
});

// 自动重启
if(config.restartTime){
	setTimeout(function(exec, execPath){
//		logger.log(execPath);
		exec(execPath);
		process.exit(0);
	}, config.restartTime * 3600 * 1000, exec, execPath);
}

var timers={};		// 任务记时器列表,存两个字段
var encrypt_key='cc40bfe6d972ce96fe3a47d0f7342cb0';
var timeConfig ;

http.request=(function(_request){
	return function(options,callback){
		var timeout=options['timeout'],
			timeoutEventId;
		var req=_request(options,function(res){
			res.on('end',function(){
				clearTimeout(timeoutEventId);
				//console.log('response end...');
			});
			
			res.on('close',function(){ //请求结束
				clearTimeout(timeoutEventId);
				//console.log('response close...');
			});
			
			res.on('abort',function(){
				//console.log('abort...');
			});
			
			callback(res);
		});
		
		//超时
		req.on('timeout',function(){
			//req.res && req.res.abort();
			//req.abort();
			req.end();
		});
		
		//如果存在超时
		timeout && (timeoutEventId=setTimeout(function(){
			req.emit('timeout',{message:'have been timeout...'});
		},timeout));
		return req;
	};
})(http.request);

queryTime(); 
//setInterval(queryTime,5);
//runTask();


/**
 *开始运行任务 2
 * @return null 
 */
function runTask(){
	if(timeConfig  != undefined){
		for(var key in timeConfig){
			var conf = timeConfig[key];
			timers[conf.lotterytype]={};
			timers[conf.lotterytype][conf.lotterytype]={timer:null,option:conf};
			try{
				if( conf.status != "-1" ) 
					run(conf);
			} catch(err){
				
//				restartTask(conf, 15);
			}
		}
	} else { //15秒之后再调用
		setTimeout(runTask, 15*1000)
	}
}

/***
 * 重启任务
 * @param conf 
 * @sleep 
 * @flag 
 */
function restartTask(conf, sleep, flag){
	
	if(sleep<=0) sleep=config.errorSleepTime;
	
	if(!timers[conf.lotterytype]) timers[conf.lotterytype]={};
	if(!timers[conf.lotterytype][conf.lotterytype]) timers[conf.lotterytype][conf.lotterytype]={timer:null,option:conf};
	
	if(flag){
		var opt;
		for(var t in timers[conf.lotterytype]){
			opt=timers[conf.lotterytype][t].option;
			clearTimeout(timers[opt.lotterytype][opt.lotterytype].timer);
			
			timers[opt.lotterytype][opt.lotterytype].timer=setTimeout(run, sleep*1000, opt);
//			log('休眠'+sleep+'秒后从采集'+opt.name+'数据...');
//			logger.log('休眠'+sleep+'秒后从采集'+opt.name+'数据...');
		}
	}else{
		clearTimeout(timers[conf.lotterytype][conf.lotterytype].timer);
		timers[conf.lotterytype][conf.lotterytype].timer=setTimeout(run, sleep*1000, conf);

//		log('休眠'+sleep+'秒后采集'+conf.lotterytype+'数据...');
//		logger.log('休眠'+sleep+'秒后采集'+conf.lotterytype+'数据...');
	}
}


//3
function run(conf){
	var tjLotteryType = conf.lotterytype ; //当前采票类型
	if(timers[tjLotteryType][tjLotteryType].timer) {
		clearTimeout(timers[tjLotteryType][tjLotteryType].timer);
	}
	var myDate = new Date();                          //当前时间
	var now = myDate.getTime();                       //获取当前时间的时间戳
//	log('开始采集'+conf.name+'数据');
	logger.log('开始采集'+conf.name+'数据');
	var option =  {  
		host : config.baseUrl,
		timeout : 30000,
		path : '/caiji/common/index/multiCj/' + tjLotteryType + "?t="+ now,         //采集指定彩种的数据
		headers : { "User-Agent" : "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) " }
	};
	http.request(option, function(res){
		var data="";
		res.on("data", function(_data){
			data+=_data.toString();
			logger.log(data);
		});
		res.on("end", function(){
			try{
				try{
					logger.log("采集" + tjLotteryType + "返回的数据" + data);
					var myDate2 = new Date();
					var useTime =  myDate2.getTime() - now;
//					logger.log("请求耗时:" +  useTime + "ms");
					var result = JSON.parse(data);					
					var CjData = result.data;	//采集结果
					var Cjsource = result.source;	//采集结果
					
					// 已经开奖
					if(null != result &&  result.status == 0){
						var sign_value = CjData.sign ;	//采集结果签名
						var kjno = CjData.prePeriod ;	//期号
						var kjcode = CjData.preOpenResult ;	//号码						
						loadForAllUser(tjLotteryType ,kjcode ,kjno ,CjData , conf , Cjsource ,sign_value ); // 发送采集结果到服务端
					} else if(result.status == 1){ 	// 正在开奖
						var everyTime = 600;
						if( tjLotteryType == 'che' ){
							everyTime = 300;
						} 
						var leftTime = parseInt(CjData.leftTime);
						var kjTime = CjData.kjTime;
						var needCaiji = CjData.needCaiji;
						
						//需要重新开奖的，休眠20秒继续开奖
						if( null != needCaiji  && parseInt(needCaiji) == 1){ 
							 restartTask(conf,2);
							 return;
						}
						if(parseInt(kjTime) < 0  && parseInt(kjTime) > everyTime){
							kjTime = 30 ;
						}
						var restartTime = 10 ;						//重启时间
						var ls_time =  everyTime - kjTime;			//开奖剩余时间	
						
						//如果提供的采集等待时间有误 则自动重启
						if(parseInt(leftTime) <= 0){
							restartTime = 1 ;  //立即
						}else if(parseInt(leftTime) > everyTime ){
							restartTime = everyTime / 2 ;	//按期时间一半自动重启
						}else if(leftTime > ls_time && leftTime <= everyTime){
							restartTime = leftTime + kjTime - everyTime;
						}
						restartTask(conf,  restartTime);	//重新启动代码
					} else if( result.status == -1){
						restartTask(conf,15);	// 默认重启
					} else if ( result.status == -2){ 
						restartTask(conf,600); // 已经禁用
					}
				}catch(err){
					logger.log(data);
					logger.log('解析'+conf.title+'数据2出错：'+err);
					throw('解析'+conf.title+'数据2出错：'+err);
				} //console.log(data);				
			}catch(err){
				logger.log('运行出错：%s，休眠%f秒'.format(err, config.errorSleepTime));
//				log('运行出错：%s，休眠%f秒'.format(err, config.errorSleepTime));
				restartTask(conf, config.errorSleepTime);
			}
			
		});
		
		res.on("error", function(err){
			log(err);
			restartTask(conf, config.errorSleepTime);
		});
		
	}).on('timeout', function(err){
		log('采集'+tjLotteryType+'数据超时');
		restartTask(conf, config.errorSleepTime);
	}).on("error", function(err){
		// 一般网络出问题会引起这个错
		log(err);
		restartTask(conf, config.errorSleepTime);
		
	}).end();
}

//数据存入 新加一个字段，签名字段sign_value；
function loadForAllUser(lotterytype,preOpenResult,prePeriod,cjData,conf,source ,sign_value){
	var apiUri  =  'm=common&c=index&a=kjForAll&lottery_type='+ lotterytype + "&source=" +source;
	var apiParm = "&fdTimeStamp=" + encodeURIComponent(cjData.fdTimeStamp)  + "&winCode=" +  encodeURIComponent(preOpenResult) + '&winPre=' + encodeURIComponent(prePeriod) + '&sign=' + sign_value;
	var option =  {  
			host : config.baseUrl,
			timeout : 30000,
			path :   "/caiji?" + apiUri + apiParm,
			headers : { "User-Agent" : "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) " }
		};
		// console.log(option);
		var myDate = new Date();
		var now = myDate.getTime();
		var sleep = cjData.leftTime + cjData.kjTime;  //休息时间
		http.request(option, function(res){
			var result="";
			res.on("data", function(_data){
				result+=_data.toString(); //console.log(_data.toString());
			});
			res.on("end", function(){
				try{
					var thisPerLine = "["+lotterytype +"] 第"+ prePeriod +"期"
					if(result=="SUCCESS"){
						thisPerLine += "推送成功；"+ result;
					}else{
						thisPerLine += "推送失败；" + "原因：" + result ;
					}
					console.log(thisPerLine);
					logger.log(thisPerLine);
				    
				    restartTask(conf, sleep, true);    //重新启动任务
				   
				}catch(err){
//					log('运行出错：%s，休眠%f秒'.format(err, config.errorSleepTime));
					restartTask(conf, config.errorSleepTime);
				}
			});
			
			res.on("error", function(err){
//				console.log(err);
				log(err);
				restartTask(conf, config.errorSleepTime);

			});
			
		}).on('timeout', function(err){
//			console.log("请求开奖超时");
			restartTask(conf, config.errorSleepTime);
		}).on("error", function(err){
			// 一般网络出问题会引起这个错
			log(err);
			restartTask(conf, config.errorSleepTime);
			
		}).end();
	
}


function requestKj(type,number){
	var option={
		host:config.submit.host,
		path:'%s/%s/%s/%'.format(config.submit.path, type, number)
	}
	
	http.get(config.submit,function(res){
		
	});
}

function createMySQLClient(){
	try{
		return mysql.createClient(config.dbinfo).on('error', function(err){
			//console.log(err);
			throw('连接数据库失败');
		});
	}catch(err){
		log('连接数据库失败：'+err);
		return false;
	}
}
//1
function queryTime(){   

	http.get("http://" + config.baseUrl +"/caiji/common/index/getLotteryConfig", function(res) {  
	var datas="";
	 res.on('data', function(data) {   //数据读取事件
		 	datas+=data.toString();  
		  });  
		 res.on('error', function(e) {   //错误产生事件
		    console.log("Got error: " + e.message);  
		});
		 
		res.on('end', function() {  //请求结束事件绑定
			//console.log(datas);
			logger.log(datas);
			try {
				var result = JSON.parse(datas);    //结果集
				//console.log(result);
				//timeConfig = result.configs;     //时间配置
				timeConfig = result;
				//console.log(timeConfig);
				runTask();
			}catch(err){ //重启服务
				logger.log(err);
			
			}
			
			
		});  
	});
}

function get_current_period(conf,data){
	var config = timeConfig[conf.title];
	if( config){
		var config = {
			lotterytype : 'jsold',
			fdTime : 120,
			beginTime : '08:30',
			endTime : '22:10',
			num: '82',
			kjTime : '150'
			
		};
		//重庆时时彩
		
		var d= config.beginTime.split(":");
		var date=new Date();
		date.setSeconds(0);
		date.setHours(d[0]);
		date.setMinutes(d[1]);
		var periodTime = 600;
		var now = new Date().getTime(); 
		var begin = date.getTime();
		console.log(data);
		var currentPeriod = Math.ceil((now + config.fdTime - begin)/(periodTime * 1000));
//		console.log(currentPeriod);
		var leftTime = periodTime - ((now - begin + config.fdTime )/1000) % (periodTime );
		console.log(begin);
		console.log(leftTime);
		/*var time=date.getTime();
		var delay= config.fdTime;*/
		return {
			'prePeriod':currentPeriod,
			'leftTime' : leftTime
		};

	}
}


app.get('/restart', function(req, res){
//	  res.send('Hello World');

//	queryTime();
	
	//setInterval(queryTime,5);
//	runTask();
//	logger.log(execPath);
//	exec(execPath);
//	process.exit(0);
	for(var key in timeConfig){
		var conf = timeConfig[key];
		clearTimeout(timers[conf.lotterytype][conf.lotterytype].timer);
	}
	
	setTimeout(queryTime, 5000);
	res.send('success');
	
	  
});

var server = app.listen(3000, function() {
	//logger.log("Listening on port 3000");
    // console.log('It is Listening on port %d', server.address().port);
});



// 前台添加数据接口
/*http.createServer(function(req, res){
	
	log('前台访问'+req.url);
	var data='';
	//res.writeHead(200, {"Content-Type": "text/plain"});
	//res.write('9999');
	//res.end();
	
	req.on('data', function(_data){
		data+=_data;
	}).on('end', function(){
		
		res.writeHead(200, {'Content-type' : 'text/html'});
		 res.write('<h1>Node.js</h1>');
		 res.end('<p>Hello World</p>');
		data=querystring.parse(data);
		var msg={},
			hash=crypto.createHash('md5');
		hash.update(data.key);
		
		//console.log(data);
		if(encrypt_key==hash.digest('hex')){
			delete data.key;
			if(req.url=='/data/add'){
				submitDataInput(data);
			}else if(req.url='/data/kj'){
				//console.log(data);
				calcJ(data, true)
			}
		}else{
			msg.errorCode=1;
			msg.errorMessage='校验不通过';
		}
		
		res.writeHead(200, {"Content-Type": "text/json"});
		res.write(JSON.stringify(msg));
		res.end();
	});
	
}).listen(8800);*/

function submitDataInput(data){
	log('提交从前台录入第'+data.number+'数据：'+data.data);
	
	try{
		var client=mysql.createClient(config.dbinfo);
	}catch(err){
		throw('连接数据库失败');
	}
	
	data.time=Math.floor((new Date(data.time)).getTime()/1000);
	client.query("insert into ldsj_data(type, time, number, data) values(?,?,?,?)", [data.type, data.time, data.number, data.data], function(err, result){
		if(err){
			//console.log(err);
			// 普通出错
			if(err.number==1062){
				// 数据已经存在
				log('第'+data.number+'期数据已经存在数据');

			}else{
				log('运行出错：'+err.message);
			}
		}else if(result){
			// 正常
			log('写入第'+data.number+'期数据成功');

			// 计算奖品
			//setTimeout(requestKj, 500, data.type, data.number);
			setTimeout(calcJ, 500, data);
		}else{
			global.log('未知运行出错');
		}
	});
	client.end();
}








